//
// Created by dg on 2024/1/2.
//

#include "BLYUVTextureFrame.h"
#include "./Log.h"
#include <string.h>

#define LOG_TAG "BLYUVTextureFrame"

BLYUVTextureFrame::BLYUVTextureFrame() {
    luma = nullptr;
    chromaB = nullptr;
    chromaR = nullptr;
    yuv_frame = nullptr;
}

BLYUVTextureFrame::~BLYUVTextureFrame() {
    if (luma) {
        delete[] luma;
        luma = nullptr;
    }

    if (chromaB) {
        delete[] chromaB;
        chromaB = nullptr;
    }

    if (chromaR) {
        delete[] chromaR;
        chromaR = nullptr;
    }

    if (yuv_frame) {
        delete[] yuv_frame;
        yuv_frame = nullptr;
    }
}

bool BLYUVTextureFrame::createTexture() {
    LOGD("enter BLYUVTextureFrame::createTexture");
    textures[0] = 0;
    textures[1] = 0;
    textures[2] = 0;

    int ret = initTexture();
    if (ret < 0) {
        LOGD("initTexture failed...");
        dealloc();
        return false;
    }
    return true;
}

void BLYUVTextureFrame::setVideoFrame(uint8_t *yuvFrame, int length) {
    if (yuv_frame == nullptr) {
        yuv_frame = new uint8_t[length];
        memset(yuv_frame, 0x00, length);
    }
    memcpy(yuv_frame, yuvFrame, length);
}

void BLYUVTextureFrame::updateTexImage(int width, int height) {
    if (yuv_frame) {
        //获取width,height
        int framewidth = width;
        int frameHeight = height;
        int halfW = framewidth >> 1;
        int halfH = frameHeight >> 1;

        if (framewidth % 16 != 0) {
            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        }

        if (luma == nullptr) {
            luma = new uint8_t[width * height];
        }

        if (chromaB == nullptr) {
            chromaB = new uint8_t[halfW * halfH];
        }

        if (chromaR == nullptr) {
            chromaR = new uint8_t[halfW * halfH];
        }

        int count = width * height;
        memcpy(luma, yuv_frame, count);
        yuv_frame += width * height;
        memcpy(chromaB, yuv_frame, halfW * halfH);
        yuv_frame += (halfW * halfH);
        count += (halfW * halfH);
        memcpy(chromaR, yuv_frame, halfW * halfH);
        yuv_frame -= count;

        const uint8_t *pixels[3] = {luma, chromaB, chromaR};
        GLsizei widths[3] = {framewidth, halfW, halfW};
        GLsizei heights[3] = {frameHeight, halfH, halfH};

        for (int i = 0; i < 3; ++i) {
            glActiveTexture(GL_TEXTURE0 + i);
            glBindTexture(GL_TEXTURE_2D, textures[i]);
//            if (checkGlError("glBindTexture")) {
//                return;
//            }
            glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, widths[i], heights[i], 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (const GLvoid *)pixels[i]);
        }
    }
}

bool BLYUVTextureFrame::bindTexture(int *uniformSamplers) {
    for (int i = 0; i < 3; ++i) {
        glActiveTexture(GL_TEXTURE0 + i);
        glBindTexture(GL_TEXTURE_2D, textures[i]);
        if (checkGlError("glBindTexture")) {
            return false;
        }
        glUniform1i(uniformSamplers[i], i);
    }

    return true;
}

void BLYUVTextureFrame::dealloc() {
    LOGD("enter BLYUVTextureFrame::dealloc");
    if (textures[0]) {
        glDeleteTextures(3, textures);
    }
}

int BLYUVTextureFrame::initTexture() {
    glGenTextures(3, textures);
    for (int i = 0; i < 3; i++) {
        glBindTexture(GL_TEXTURE_2D, textures[i]);
//        if (checkGlError("glBindTexture")) {
//            return -1;
//        }
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//        if (checkGlError("glTexParameteri")) {
//            return -1;
//        }
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//        if (checkGlError("glTexParameteri")) {
//            return -1;
//        }
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//        if (checkGlError("glTexParameteri")) {
//            return -1;
//        }
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//        if (checkGlError("glTexParameteri")) {
//            return -1;
//        }
    }
    return 1;
}